package com.enzoism.springboot.dive.bis.iterator;

import java.util.*;
import java.util.Iterator;
import java.util.function.Consumer;

/**
 * 【原生】通过伪代码理解迭代器的核心内容
 *  高仿Vector迭代器-可以理解只添加了锁
 * @param <E>
 */
public class MyVectorList<E> {
    // 内部的elementData的操作次数(因为没有加锁，用这个来判断是否有其他线程修改了当前对象)
    int modCount;
    // 数组的size
    int size;
    // 内部维护的数组
    Object[] elementData;
    // 对象移除方法
    public boolean remove(Object o) {
        return removeElement(o);
    }
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj,0);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            for (int i = index; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= size) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                    size);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = size - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        size--;
        elementData[size] = null; /* to let gc do its work */
    }

    //-----------------迭代器-----------------//
    /**
     *     ArrayList默认的迭代器就是Itr，可以进行对象移除
     *     1）添加-使用ListIterator进行添加
     *     2）删除-使用Iterator进行移除
     *     public Iterator<E> iterator() {
     *         return new Itr();
     *     }
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            synchronized (MyVectorList.this) {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (MyVectorList.this) {
                checkForComodification();
                MyVectorList.this.remove(lastRet);
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }

        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            synchronized (MyVectorList.this) {
                final int size = MyVectorList.this.size;
                int i = cursor;
                if (i >= size) {
                    return;
                }
                @SuppressWarnings("unchecked")
                final E[] elementData = (E[]) MyVectorList.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    action.accept(elementData[i++]);
                }
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }


}